import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { CategoryService } from 'src/modules/category/category.service';
import { EventToPlayerService } from 'src/modules/event-to-player/event-to-player.service';
import { EventService } from 'src/modules/event/event.service';
import { GameService } from 'src/modules/game/game.service';
import { GroupPlayerScoreService } from 'src/modules/group-player-score/group-player-score.service';
import { GroupService } from 'src/modules/group/group.service';
import { MatchService } from 'src/modules/match/match.service';
import { PlayerSignupService } from 'src/modules/player-signup/service/player-signup.service';
import { StageEventService } from 'src/modules/stage-event/stage-event.service';
import { StageService } from 'src/modules/stage/stage.service';
import { TournamentService } from 'src/modules/tournament/tournament.service';
import { CopyDataDto } from '../dto/copy-data.dto';
import logger from 'src/common/utils/log';
import {
  CategoryStatusEnum,
  CopyTypeEnum,
  EventStatusEnum,
  GroupStatusEnum,
  MatchPlayerStatusEnum,
  MatchStatusEnum,
  StageStatusEnum,
  TournamentStatusEnum,
} from 'src/common/constant/enums';
import { CreateTournamentDto } from 'src/modules/tournament/dto/create-tournament.dto';
import { CreateCategoryDto } from 'src/modules/category/dto/create-category.dto';
import { Category } from 'src/modules/category/entities/category.entity';
import { CreateEventDto } from 'src/modules/event/dto/create-event.dto';
import { Event } from 'src/modules/event/entities/event.entity';
import { EventToPlayer } from 'src/modules/event-to-player/entities/event-to-player.entity';
import { PlayerSignup } from 'src/modules/player-signup/entities/player-signup.entity';
import { Stage } from 'src/modules/stage/entities/stage.entity';
import { Group } from 'src/modules/group/entities/group.entity';
import { StageEvent } from 'src/modules/stage-event/entities/stage-event.entity';
import { MatchInfo } from 'src/modules/match/entities/match.entity';
import { GameInfo } from 'src/modules/game/entities/game.entity';
import { GroupPlayerScore } from 'src/modules/group-player-score/entities/group-player-score.entity';
import { GameInfoV2 } from 'src/modules/game/entities/game.entity.v2';

type copySession = {
  tournamentId?: number;
  categoryId?: number;
  eventId?: number;
  stageId?: number;
  groupId?: number;
  matchId?: number;
  eventToPlayer?: EventToPlayer[];
  playerSignup?: PlayerSignup[];
  type: CopyTypeEnum;
  tournamentStatus?: TournamentStatusEnum;
  categoryStatus?: CategoryStatusEnum;
  eventStatus?: EventStatusEnum;
  stageStatus?: StageStatusEnum;
  groupStatus?: GroupStatusEnum;
  matchStatus?: MatchStatusEnum;
  createBy?: number;
};

@Injectable()
export class CopyDataService {
  constructor(
    private readonly groupService: GroupService,
    private readonly stageEventService: StageEventService,
    private readonly groupPlayerScoreService: GroupPlayerScoreService,
    private readonly matchService: MatchService,
    private readonly stageService: StageService,
    private readonly gameService: GameService,
    private readonly eventService: EventService,
    private readonly eventToPlayerService: EventToPlayerService,
    private readonly playerSignupService: PlayerSignupService,
    private readonly categoryService: CategoryService,
    private readonly tournamentService: TournamentService,
  ) {}
  getAllDataStatus(type: CopyTypeEnum) {
    if (
      [
        CopyTypeEnum.Created,
        CopyTypeEnum.Signup,
        CopyTypeEnum.Settle,
        CopyTypeEnum.Schedule,
      ].includes(type)
    ) {
      return {
        tournamentStatus: TournamentStatusEnum.Created,
        categoryStatus: CategoryStatusEnum.Created,
        eventStatus: EventStatusEnum.Created,
        stageStatus: StageStatusEnum.Created,
        groupStatus: GroupStatusEnum.Created,
        matchStatus: MatchStatusEnum.Created,
      };
    } else {
      return {};
    }
  }
  async copyTournament(copyDataDto: CopyDataDto) {
    const { tournamentName, tournamentId, type, user } = copyDataDto;
    logger.info(`copyTournament... ${tournamentId}, ${tournamentName}`);
    const tournament =
      await this.tournamentService.getByIdWithCategories(tournamentId);
    if (!tournament) {
      throw new HttpException(
        ' tournament not found',
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
    const allDataStatus = this.getAllDataStatus(type);
    const { categories, ...baseTournament } = tournament;
    const newTournament = Object.assign({}, baseTournament);
    newTournament.id = undefined;
    newTournament.name = tournamentName || newTournament.name;
    newTournament.status =
      allDataStatus.tournamentStatus || baseTournament.status;
    newTournament.createTime = new Date();
    newTournament.updateTime = new Date();
    const savedTournament = await this.tournamentService.create(
      newTournament as unknown as CreateTournamentDto,
    );
    const categoryIds = categories.map((category) => {
      return category.id;
    });
    const copySession = {
      tournamentId: savedTournament.id,
      type,
      createBy: user.id,
      ...allDataStatus,
    };
    savedTournament.categories = await this.copyCategory(
      categoryIds,
      copySession,
    );
    return savedTournament;
  }
  async copyCategory(
    categoryIds: number[],
    copySession: copySession,
  ): Promise<Category[]> {
    logger.info(`copyCategory... categoryIds: ${JSON.stringify(categoryIds)}`);
    const copiedCategories: Category[] = [];

    for (const categoryId of categoryIds) {
      const category = await this.categoryService.getByIdWithEvents(categoryId);
      if (!category) {
        logger.error(`Category with ID ${categoryId} not found`);
        throw new HttpException(
          `Category with ID ${categoryId} not found`,
          HttpStatus.INTERNAL_SERVER_ERROR,
        );
      }

      const { events, ...baseCategory } = category;
      const newCategory = Object.assign({}, baseCategory);
      newCategory.id = undefined;
      newCategory.name = `${newCategory.name}`; // 添加复制标识
      newCategory.status = copySession.categoryStatus || baseCategory.status;
      newCategory.createTime = new Date();
      newCategory.updateTime = new Date();
      newCategory.tournamentId = copySession.tournamentId;
      newCategory.createBy = copySession.createBy;
      newCategory.updateBy = copySession.createBy;

      const createdCategory = await this.categoryService.create(
        newCategory as unknown as CreateCategoryDto,
      );
      const eventIds = events.map((event) => {
        return event.id;
      });
      createdCategory.events = await this.copyEvent(eventIds, {
        categoryId: createdCategory.id,
        ...copySession,
      });
      copiedCategories.push(createdCategory);
    }
    return copiedCategories;
  }
  async copyEvent(
    eventIds: number[],
    copySession: copySession,
  ): Promise<Event[]> {
    logger.info(`copyEvent... eventIds: ${JSON.stringify(eventIds)}`);
    const copiedEvents: Event[] = [];
    const { type } = copySession;
    const isSignupPlayer = type >= CopyTypeEnum.Signup;

    for (const eventId of eventIds) {
      // 获取原事件数据（包含关联关系）
      const event = await this.eventService.findById(eventId);
      if (!event) {
        logger.error(`Event with ID ${eventId} not found`);
        throw new HttpException(
          `Event with ID ${eventId} not found`,
          HttpStatus.INTERNAL_SERVER_ERROR,
        );
      }

      // 解构原事件数据，排除关联对象和ID
      const { id, ...baseEvent } = event;

      // 创建新事件对象
      const newEvent = Object.assign({}, baseEvent);
      newEvent.name = `${newEvent.name}`; // 添加复制标识
      newEvent.status = copySession.eventStatus || baseEvent.status; // 重置状态为创建态
      newEvent.createTime = new Date();
      newEvent.updateTime = new Date();
      newEvent.categoryId = copySession.categoryId;
      newEvent.tournamentId = copySession.tournamentId;
      newEvent.createBy = copySession.createBy;
      newEvent.updateBy = copySession.createBy;

      // 保存基础事件信息
      const createdEvent = await this.eventService.create(
        newEvent as unknown as CreateEventDto,
      );
      logger.info(`Created base event: ${createdEvent.id}`);
      const newCopySession = { ...copySession, eventId: createdEvent.id };

      // 递归复制关联的阶段数据
      if (isSignupPlayer) {
        createdEvent.playerSignups = await this.copyPlayerSignups(
          id,
          newCopySession,
        );
      }

      createdEvent.eventToPlayers = await this.copyEventToPlayers(
        id,
        newCopySession,
      );

      createdEvent.stages = await this.copyStages(id, newCopySession);

      copiedEvents.push(createdEvent);
    }

    return copiedEvents;
  }
  // 辅助方法：复制事件-选手关联数据
  private async copyEventToPlayers(
    eventId: number,
    copySession: copySession,
  ): Promise<EventToPlayer[]> {
    logger.info(
      `copyEventToPlayers... originalEventId: ${eventId}, newEventId: ${copySession.eventId}`,
    );
    const copiedEventToPlayers: EventToPlayer[] = [];
    const { type } = copySession;
    const isSettlePlayer = type >= CopyTypeEnum.Settle;

    // 获取原事件关联的所有选手关系数据
    const originalEventToPlayers =
      await this.eventToPlayerService.findByEventId(eventId);
    if (!originalEventToPlayers.length) {
      logger.info(`No EventToPlayer records found for eventId: ${eventId}`);
      return copiedEventToPlayers;
    }

    const savedEventToPlayers = originalEventToPlayers.map((original) => {
      const newEventToPlayer = Object.assign({}, original);
      newEventToPlayer.id = undefined; // 重置自增ID
      newEventToPlayer.eventId = copySession.eventId; // 关联到新事件ID
      newEventToPlayer.copyFromId = original.id;

      const player1 = !isSettlePlayer
        ? null
        : copySession.playerSignup.find(
            (player) => player.copyFromId === original.player1Id,
          );
      const player2 = !isSettlePlayer
        ? null
        : copySession.playerSignup.find(
            (player) => player.copyFromId === original.player2Id,
          );

      newEventToPlayer.player1Id = player1?.id;
      newEventToPlayer.player2Id = player2?.id;
      newEventToPlayer.player1Name = original?.player1Name;
      newEventToPlayer.player2Name = original?.player2Name;

      // 处理stage内唯一标识（保留原索引结构确保一致性）
      // 如需避免冲突可添加复制标识：`${original.registrationIndex}_copy`
      newEventToPlayer.registrationIndex = original.registrationIndex;
      newEventToPlayer.stageOrderInEvent = original.stageOrderInEvent;

      return newEventToPlayer;
    });

    const res = await this.eventToPlayerService.saveList(savedEventToPlayers);
    copySession.eventToPlayer = res;
    return res;
  }

  // 辅助方法：复制选手报名数据
  private async copyPlayerSignups(eventId: number, copySession: copySession) {
    const playerSignups =
      await this.playerSignupService.ListByEventIdForTopPlayer(eventId);

    const newPlayerSignups = playerSignups.map((playerSignup) => {
      const newPlayerSignup = Object.assign({}, playerSignup);
      newPlayerSignup.id = undefined;
      newPlayerSignup.eventId = copySession.eventId;
      newPlayerSignup.createTime = new Date();
      newPlayerSignup.updateTime = new Date();
      newPlayerSignup.parentPlayerId = undefined;
      newPlayerSignup.key = `${playerSignup.key}_copy`;
      newPlayerSignup.copyFromId = playerSignup.id;
      newPlayerSignup.createBy = copySession.createBy;
      newPlayerSignup.updateBy = copySession.createBy;
      if (
        newPlayerSignup.subPlayerSignups &&
        newPlayerSignup.subPlayerSignups.length > 0
      ) {
        newPlayerSignup.subPlayerSignups = newPlayerSignup.subPlayerSignups.map(
          (subPlayerSignup) => {
            return {
              ...subPlayerSignup,
              id: undefined,
              eventId: copySession.eventId,
              createTime: new Date(),
              updateTime: new Date(),
              parentPlayerId: undefined,
              key: `${subPlayerSignup.key}_copy`,
              copyFromId: subPlayerSignup.id,
            };
          },
        );
      }
      return newPlayerSignup;
    });
    const saveRes = await this.playerSignupService.saveList(newPlayerSignups);
    copySession.playerSignup = copySession.playerSignup || [];
    saveRes.forEach((item) => {
      copySession.playerSignup.push(item);
      if (item.subPlayerSignups) {
        item.subPlayerSignups.forEach((subItem) => {
          copySession.playerSignup.push(subItem);
        });
      }
    });
    return saveRes;
  }
  private async copyStages(
    eventId: number,
    copySession: copySession,
  ): Promise<Stage[]> {
    logger.info(
      `copyStages... originalEventId: ${eventId}, newEventId: ${copySession.eventId}`,
    );

    // 获取新事件ID
    const newEventId = copySession.eventId;
    if (!newEventId) {
      logger.error('New event ID not found in copy session');
      return [];
    }

    // 获取原事件的所有阶段数据（包含关联的组和阶段事件）
    const originalStages = await this.stageService.listByEventId(eventId);
    if (!originalStages.length) {
      logger.info(`No stages found for eventId: ${eventId}`);
      return [];
    }

    // 批量创建新阶段实体
    const newStages = originalStages.map((stage) =>
      this.createNewStage(stage, newEventId, copySession),
    );
    const savedStages = await this.stageService.saveList(newStages as any);

    // 创建原阶段ID到新阶段ID的映射
    const _stageIdMap = {};
    savedStages.forEach((stage) => {
      if (stage.copyFromId) {
        _stageIdMap[stage.copyFromId] = stage.id;
      }
    });

    // 递归复制每个阶段的子数据
    for (const stage of savedStages) {
      const originalStage = originalStages.find(
        (os) => os.id === stage.copyFromId,
      );
      if (!originalStage) continue;

      // 更新会话上下文
      const stageCopySession = { ...copySession, stageId: stage.id };

      // 复制组数据
      stage.groups = await this.copyGroups(originalStage.id, stageCopySession);

      // 复制阶段事件数据
      stage.stageEvents = await this.copyStageEvents(
        originalStage.id,
        stageCopySession,
      );

      // 处理阶段间依赖（如玩家来源阶段）
      if (originalStage.playerSourceStageId) {
        stage.playerSourceStageId =
          _stageIdMap[originalStage.playerSourceStageId] || null;
      }
    }

    // 保存包含子数据的完整阶段信息
    const finalStages = await this.stageService.saveList(savedStages as any);
    logger.info(
      `Successfully copied ${finalStages.length} stages with related data`,
    );

    return finalStages;
  }

  // 辅助方法：创建新的阶段实体
  private createNewStage(
    original: Stage,
    newEventId: number,
    copySession: copySession,
  ): Stage {
    const newStage = new Stage();
    Object.assign(newStage, original);

    // 重置核心字段
    newStage.id = undefined;
    newStage.eventId = newEventId;
    newStage.tournamentId = copySession.tournamentId || original.tournamentId;
    newStage.categoryId = copySession.categoryId || original.categoryId;
    newStage.status = copySession.stageStatus || newStage.status;
    newStage.createTime = new Date();
    newStage.updateTime = new Date();
    newStage.copyFromId = original.id;
    newStage.createBy = copySession.createBy;
    newStage.updateBy = copySession.createBy;

    // 清除关联数据引用（将在后续步骤中重新关联）
    newStage.groups = [];
    newStage.stageEvents = [];

    return newStage;
  }

  // 辅助方法：复制阶段关联的组数据
  private async copyGroups(
    originalStageId: number,
    copySession: copySession,
  ): Promise<Group[]> {
    logger.info(
      `Starting to copy groups for original stage ID: ${originalStageId}`,
    );

    // 获取原始阶段下的所有组
    const originalGroups =
      await this.groupService.listByStageId(originalStageId);

    if (originalGroups.length === 0) {
      logger.info(`No groups found for original stage ID: ${originalStageId}`);
      return [];
    }

    // 验证复制会话中的新阶段ID
    if (!copySession.stageId) {
      logger.error('New stage ID not found in copy session');
      throw new Error('Missing new stage ID in copy session');
    }

    // 创建新组数组并复制属性
    const newGroups = originalGroups.map((group) => {
      const newGroup = new Group();
      Object.assign(newGroup, group);
      newGroup.id = undefined;
      newGroup.name = `${group.name}`; // 添加复制标识
      newGroup.groupIndex = group.groupIndex;
      newGroup.status = copySession.groupStatus || newGroup.status; // 重置为初始状态
      newGroup.stageId = copySession.stageId;
      newGroup.createTime = new Date();
      newGroup.updateTime = new Date();
      newGroup.createBy = copySession.createBy;
      newGroup.updateBy = copySession.createBy;
      // 关联到新阶段
      // createTime和updateTime由实体钩子自动处理
      return newGroup;
    });

    // 批量保存新组
    const savedGroups = await this.groupService.saveList(newGroups);
    logger.info(
      `Successfully copied ${savedGroups.length} groups to new stage ID: ${copySession.stageId}`,
    );

    // 复制组关联的比赛信息和玩家分数
    for (const group of savedGroups) {
      const originalGroup = originalGroups.find(
        (g) => g.groupIndex === group.groupIndex,
      );
      const newCopySession = {
        ...copySession,
        groupId: group.id,
      };
      if (originalGroup) {
        // 复制组内比赛信息
        group.matchInfos = await this.copyMatchInfos(
          originalGroup.id,
          newCopySession,
        );
        // 复制组玩家分数
        if (copySession.type >= CopyTypeEnum.All) {
          group.groupPlayerScores = await this.copyGroupPlayerScores(
            originalGroup.id,
            newCopySession,
          );
        }
      }
    }

    return savedGroups;
  }
  private async copyGroupPlayerScores(
    originalGroupId: number,
    copySession: copySession,
  ) {
    logger.info(
      `Copying group player scores for original group ID: ${originalGroupId}`,
    );

    // 获取原始组的玩家分数数据
    const originalScores =
      await this.groupPlayerScoreService.listByGroupId(originalGroupId);

    if (originalScores.length === 0) {
      logger.info(
        `No player scores found for original group ID: ${originalGroupId}`,
      );
      return [];
    }

    // 验证复制会话中的新组ID
    if (!copySession.groupId) {
      logger.error('New group ID not found in copy session');
      throw new Error('Missing new group ID in copy session');
    }

    // 创建原始玩家ID到新玩家ID的映射
    const playerIdMap = new Map<number, number>();
    if (copySession.eventToPlayer) {
      copySession.eventToPlayer.forEach((player) => {
        if (player.copyFromId) {
          playerIdMap.set(player.copyFromId, player.id);
        }
      });
    }

    // 创建新的玩家分数实体数组
    const newScores = originalScores.map((originalScore) => {
      const newScore = new GroupPlayerScore();
      Object.assign(newScore, originalScore);

      // 重置ID并设置新组ID
      newScore.id = undefined;
      newScore.groupId = copySession.groupId;

      // 映射新的玩家ID
      if (originalScore.playerId && playerIdMap.has(originalScore.playerId)) {
        newScore.playerId = playerIdMap.get(originalScore.playerId);
      } else {
        logger.warn(
          `Could not find new player ID for original player ID: ${originalScore.playerId}`,
        );
      }
      return newScore;
    });

    // 批量保存新的玩家分数
    const savedScores = await this.groupPlayerScoreService.saveList(newScores);
    logger.info(
      `Successfully copied ${savedScores.length} group player scores`,
    );

    return savedScores;
  }

  // 辅助方法：复制阶段事件数据
  private async copyStageEvents(
    originalStageId: number,
    copySession: copySession,
  ): Promise<StageEvent[]> {
    logger.info(
      `Starting to copy stage events for original stage ID: ${originalStageId}`,
    );

    // 获取原始阶段事件数据
    const originalStageEvents =
      await this.stageEventService.findByStageId(originalStageId);

    if (originalStageEvents.length === 0) {
      logger.info(
        `No stage events found for original stage ID: ${originalStageId}`,
      );
      return [];
    }

    // 验证复制会话中的新阶段ID
    if (!copySession.stageId) {
      logger.error('New stage ID not found in copy session');
      throw new HttpException(
        'Missing new stage ID in copy session',
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }

    // 创建新的阶段事件数组并复制属性
    const newStageEvents = originalStageEvents.map((event) => {
      const newEvent = new StageEvent();
      Object.assign(newEvent, event);
      newEvent.stageId = copySession.stageId!;
      newEvent.eventOrder = event.eventOrder;
      newEvent.type = event.type;
      newEvent.createTime = new Date();
      newEvent.updateTime = new Date();
      // createTime和updateTime由实体的BeforeInsert/BeforeUpdate钩子自动处理
      return newEvent;
    });

    // 批量保存新的阶段事件
    const savedEvents = await this.stageEventService.saveList(newStageEvents);
    logger.info(
      `Successfully copied ${savedEvents.length} stage events to new stage ID: ${copySession.stageId}`,
    );

    return savedEvents;
  }

  private async copyMatchInfos(
    originGroupId: number,
    copySession: copySession,
  ): Promise<MatchInfo[]> {
    logger.info(
      `Starting to copy match infos for original group ID: ${originGroupId}`,
    );
    const { type } = copySession;
    const isScheduleMatch = type >= CopyTypeEnum.Schedule;
    const isCopyAllMatch = type >= CopyTypeEnum.All;

    // 获取原始组的所有比赛信息（包含子比赛和游戏数据）
    const originalMatches = await this.matchService.getByGroupId(originGroupId);

    if (originalMatches.length === 0) {
      logger.info(
        `No match infos found for original group ID: ${originGroupId}`,
      );
      return [];
    }

    // 验证复制会话中的必要参数
    if (!copySession.groupId) {
      logger.error('New group ID not found in copy session');
      throw new Error('Missing new group ID in copy session');
    }

    // 存储原始比赛ID到新比赛ID的映射关系
    const newMatches: MatchInfo[] = [];

    // 第一步：复制主比赛信息（不含子比赛和游戏）
    for (const original of originalMatches) {
      const newMatch = new MatchInfo();
      Object.assign(newMatch, original);
      // 复制基础属性并重置ID
      newMatch.id = undefined;
      newMatch.groupId = copySession.groupId;
      newMatch.tournamentId = copySession.tournamentId;
      newMatch.categoryId = copySession.categoryId;
      newMatch.eventId = copySession.eventId;
      newMatch.stageId = copySession.stageId;
      newMatch.groupId = copySession.groupId;
      newMatch.subMatchId = null;
      // 映射选手关联ID（从copySession获取新的EventToPlayer ID）
      newMatch.homePlayerId = this.getCopiedEventToPlayerId(
        original.homePlayerId,
        copySession,
      );
      newMatch.awayPlayerId = this.getCopiedEventToPlayerId(
        original.awayPlayerId,
        copySession,
      );
      // newMatch.winnerId = original.winnerId
      //   ? this.getCopiedEventToPlayerId(original.winnerId, copySession)
      //   : null;
      newMatch.winnerId = null;
      // 重置比赛状态和分数
      newMatch.status = copySession.matchStatus || newMatch.status;
      newMatch.homePlayerStatus = MatchPlayerStatusEnum.NotCheckIn;
      newMatch.awayPlayerStatus = MatchPlayerStatusEnum.NotCheckIn;
      newMatch.homePlayerRally = isCopyAllMatch ? newMatch.homePlayerRally : 0;
      newMatch.awayPlayerRally = isCopyAllMatch ? newMatch.awayPlayerRally : 0;
      newMatch.estimatedStart = isScheduleMatch
        ? original.estimatedStart
        : null;
      newMatch.estimatedEnd = isScheduleMatch ? original.estimatedEnd : null;
      newMatch.playgroundId = isScheduleMatch ? original.playgroundId : null;
      newMatch.actualStart = null;
      newMatch.actualEnd = null;
      newMatch.copyFromId = original.id;
      newMatch.createBy = copySession.createBy;
      newMatch.updateBy = copySession.createBy;
      if (newMatch.subMatchInfos && newMatch.subMatchInfos.length > 0) {
        newMatch.subMatchInfos = newMatch.subMatchInfos.map((subMatch) => {
          const newSubMatch = new MatchInfo();
          Object.assign(newSubMatch, subMatch);
          newSubMatch.id = undefined;
          newSubMatch.groupId = copySession.groupId;
          newSubMatch.tournamentId = copySession.tournamentId;
          newSubMatch.categoryId = copySession.categoryId;
          newSubMatch.eventId = copySession.eventId;
          newSubMatch.stageId = copySession.stageId;
          newSubMatch.groupId = copySession.groupId;
          newSubMatch.subMatchId = null;
          // 映射选手关联ID（从copySession获取新的EventToPlayer ID）
          newSubMatch.homePlayerId = this.getCopiedEventToPlayerId(
            subMatch.homePlayerId,
            copySession,
          );
          newSubMatch.awayPlayerId = this.getCopiedEventToPlayerId(
            subMatch.awayPlayerId,
            copySession,
          );
          // newMatch.winnerId = original.winnerId
          //   ? this.getCopiedEventToPlayerId(original.winnerId, copySession)
          //   : null;
          newSubMatch.winnerId = null;
          // 重置比赛状态和分数
          newSubMatch.status = copySession.matchStatus || newSubMatch.status;
          newSubMatch.homePlayerStatus = MatchPlayerStatusEnum.NotCheckIn;
          newSubMatch.awayPlayerStatus = MatchPlayerStatusEnum.NotCheckIn;
          newSubMatch.homePlayerRally = isCopyAllMatch
            ? newSubMatch.homePlayerRally
            : 0;
          newSubMatch.awayPlayerRally = isCopyAllMatch
            ? newSubMatch.awayPlayerRally
            : 0;
          newSubMatch.estimatedStart = isScheduleMatch
            ? newSubMatch.estimatedStart
            : null;
          newSubMatch.estimatedEnd = isScheduleMatch
            ? newSubMatch.estimatedEnd
            : null;
          newSubMatch.playgroundId = isScheduleMatch
            ? newSubMatch.playgroundId
            : null;
          newSubMatch.actualStart = null;
          newSubMatch.actualEnd = null;
          newSubMatch.copyFromId = subMatch.id;
          newSubMatch.createBy = copySession.createBy;
          newSubMatch.updateBy = copySession.createBy;
          return newSubMatch;
        });
      }

      newMatches.push(newMatch);
    }

    // 批量保存主比赛信息以获取新ID
    const savedMainMatches = await this.matchService.saveList(newMatches);

    if (isCopyAllMatch) {
      for (const savedMatch of savedMainMatches) {
        const newCopySession = {
          ...copySession,
          matchId: savedMainMatches[0].id,
        };
        savedMatch.games = await this.copyGames(
          savedMatch.copyFromId,
          newCopySession,
        );
      }
    }

    // 复制游戏信息
    // if (original.games && original.games.length > 0) {
    //   const games = await this.copyGames(
    //     original.games,
    //     savedMatch.id,
    //     copySession,
    //   );
    //   savedMatch.games = games;
    // }
    logger.info(
      `Successfully copied ${savedMainMatches.length} match infos to new group ID: ${copySession.groupId}`,
    );

    return savedMainMatches;
  }

  // 辅助方法：复制子比赛信息
  // private async copySubMatchInfos(
  //   originalSubMatches: MatchInfo[],
  //   parentMatchId: number,
  //   copySession: copySession,
  //   matchIdMap: Map<number, number>,
  // ): Promise<MatchInfo[]> {
  //   // 实现子比赛复制逻辑（类似主比赛复制，但需要设置parentMatchId）
  //   // ...
  // }

  // 辅助方法：复制游戏信息
  private async copyGames(
    originalMatchId: number,
    copySession: copySession,
  ): Promise<GameInfo[]> {
    logger.info(
      `copyGames... originalMatchId: ${originalMatchId}, newMatchId: ${copySession.matchId}`,
    );
    const originalGames = await this.gameService.findByMatchId(originalMatchId);
    if (!originalGames.length) {
      logger.info(`No games found for original match ID: ${originalMatchId}`);
      return [];
    }

    // 创建选手ID映射表 (原始选手ID -> 新选手ID)
    const playerIdMap = new Map<number, number>();
    copySession.eventToPlayer?.forEach((etp) => {
      if (etp.copyFromId) {
        playerIdMap.set(etp.copyFromId, etp.id);
      }
    });

    const newGames = originalGames.map((original) => {
      const newGame = new GameInfoV2();
      Object.assign(newGame, original);

      // 重置ID和关联关系
      newGame.id = undefined;
      newGame.matchId = copySession.matchId!;
      newGame.createTime = new Date();
      newGame.updateTime = new Date();

      // 更新选手ID映射
      newGame.homePlayerId = playerIdMap.get(original.homePlayerId);
      newGame.awayPlayerId = playerIdMap.get(original.awayPlayerId);
      newGame.winnerId = original.winnerId
        ? playerIdMap.get(original.winnerId)
        : null;

      // 重置比分相关字段（如果是新建状态）
      if (copySession.matchStatus === MatchStatusEnum.Created) {
        newGame.homePlayerRally = 0;
        newGame.awayPlayerRally = 0;
        newGame.progress = null;
        newGame.startTime = null;
        newGame.endTime = null;
        newGame.status = original.status;
      }

      return newGame;
    });

    const savedGames = await this.gameService.saveList(newGames);
    logger.info(
      `Successfully copied ${savedGames.length} games for match ${copySession.matchId}`,
    );
    return savedGames;
  }

  // 辅助方法：获取复制后的选手关联ID
  private getCopiedEventToPlayerId(
    originalPlayerId: number,
    copySession: copySession,
  ): number {
    if (originalPlayerId === null) {
      // 这个地方意味5在创建比赛时无法预估，大概率是淘汰赛的决赛阶段
      return null;
    }
    const copiedPlayer = copySession.eventToPlayer?.find(
      (etp) => etp.copyFromId === originalPlayerId,
    );
    if (!copiedPlayer) {
      logger.error(
        `Copied player not found for original ID: ${originalPlayerId}`,
      );
      throw new Error(
        `Missing copied player data for original ID: ${originalPlayerId}`,
      );
    }
    return copiedPlayer.id;
  }
}
